home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume24 / yabbawhap / part01 next >
Encoding:
Internet Message Format  |  1991-10-09  |  52.6 KB

  1. Subject:  v24i073:  Public-domain replacement for compress programs, Part01/04
  2. Newsgroups: comp.sources.unix
  3. Approved: rsalz@uunet.UU.NET
  4. X-Checksum-Snefru: d84d6380 b5e3c68c cc5c4bff f34fbc20
  5.  
  6. Submitted-by: Dan Bernstein <brnstnd@nyu.edu>
  7. Posting-number: Volume 24, Issue 73
  8. Archive-name: yabbawhap/part01
  9.  
  10. [ The file PATENT gives a nice summary of the issues.  --r$ ]
  11.  
  12. yabba applies Y compression to its input; unyabba decompresses the
  13. result. whap applies AP compression to its input; unwhap decompresses
  14. the result. whap and unwhap run at about the same speed as UNIX compress
  15. and uncompress, which use LZW coding; yabba and unyabba are two to three
  16. times slower. AP and Y compression are typically 10-20% more effective
  17. than LZW compression in the same amount of memory. Y coding, unlike LZW
  18. coding and AP coding, is unpatented. It should be possible to use these
  19. programs on any reasonable C platform, though they were originally
  20. designed on a BSD UNIX system.
  21.  
  22. #! /bin/sh
  23. # This is a shell archive.  Remove anything before this line, then feed it
  24. # into a shell via "sh file" or similar.  To overwrite existing files,
  25. # type "sh file -c".
  26. # The tool that generated this appeared in the comp.sources.unix newsgroup;
  27. # send mail to comp-sources-unix@uunet.uu.net if you want that tool.
  28. # Contents:  README Makefile ycoding.4b
  29. # Wrapped by rsalz@litchi.bbn.com on Wed Mar 20 17:09:21 1991
  30. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  31. echo If this archive is complete, you will see the following message:
  32. echo '          "shar: End of archive 1 (of 4)."'
  33. if test -f 'README' -a "${1}" != "-c" ; then 
  34.   echo shar: Will not clobber existing file \"'README'\"
  35. else
  36.   echo shar: Extracting \"'README'\" \(8502 characters\)
  37.   sed "s/^X//" >'README' <<'END_OF_FILE'
  38. Xyabbawhap - Y and AP compression filters
  39. X
  40. Xyabba applies Y compression to its input; unyabba decompresses the
  41. Xresult. whap applies AP compression to its input; unwhap decompresses
  42. Xthe result. whap and unwhap run at about the same speed as UNIX compress
  43. Xand uncompress, which use LZW coding; yabba and unyabba are two to three
  44. Xtimes slower. AP and Y compression are typically 10-20% more effective
  45. Xthan LZW compression in the same amount of memory. Y coding, unlike LZW
  46. Xcoding and AP coding, is unpatented. It should be possible to use these
  47. Xprograms on any reasonable C platform, though they were originally
  48. Xdesigned on a BSD UNIX system.
  49. X
  50. Xyabbawhap version 1.00, March 19, 1991.
  51. XPlaced into the public domain by Daniel J. Bernstein.
  52. X
  53. XThanks to the gamma testers for their comments, criticism, and code:
  54. X
  55. X  Eirik Fuller <eirik@theory.tn.cornell.edu>
  56. X  Marc Andreessen <andreessen@uimrl7.mrl.uiuc.edu>
  57. X  Loren J. Rittle <cs326ag@ux1.cso.uiuc.edu>
  58. X  Jean-loup Gailly <jloup@chorus.fr>
  59. X  Terje Malmedal <malmedal@dhmolde.no>
  60. X  Lennart Augustsson <augustss@cs.chalmers.se>
  61. X  John C. Schultz <schultz@halley.serc.3m.com>
  62. X  Dave Gudeman <gudeman@cs.arizona.edu>
  63. X  Colin Plumb <ccplumb@rose.waterloo.edu>
  64. X  Ozan Yigit <oz@nexus.yorku.ca>
  65. X  Benno Tietz <tietz@cs.bonn.edu>
  66. X  Alexios Zavras <zvr@theseas.ntua.gr>
  67. X  Hans Henrik Eriksen <hhe@ifi.uio.no>
  68. X  Frank Wales <frank@grep.co.uk>
  69. X  Paul A. Houle <pahsnsr@jupiter.nmt.edu>
  70. X  Graham Thoal <gtoal@ed.ac.uk>
  71. X  Robert Kelley <rjk@sequent.com>
  72. X
  73. X
  74. XOrganization of README:
  75. X
  76. X1. Files
  77. X2. Requirements
  78. X3. How to configure
  79. X4. How to compile
  80. X5. How to install
  81. X6. TODO list
  82. X
  83. X
  84. X1. Files:
  85. X
  86. XBLURB        advertisement
  87. XCHANGES      list of changes since first distributed version
  88. XREADME       this file
  89. XFORMLETTER   form letter to send to the author
  90. XPATENTS      some notes on compression patents
  91. XQUESTIONS    questions and answers about yabbawhap
  92. XFILES        file list
  93. Xsysconf      script to test for certain system features
  94. Xcheckconf.c  tool to ease Makefile configuration
  95. XMakefile     compilation commands
  96. Xtry          script to test yabba and unyabba and compare to compress
  97. Xtryap        script to test whap and unwhap and compare to compress
  98. Xtryapy       combination of try and tryap
  99. XINSTALL      script to install the programs
  100. Xyabba.1      man page for yabba and whap
  101. Xunyabba.1    man page for unyabba and unwhap
  102. Xhuptrie.h    huptrie library
  103. Xbitout.h     bit output library
  104. Xpercent.h    percent library, computes 100a/b without overflow
  105. Xtexts.h      various messages printed by the programs
  106. Xyw.c         main code for yabba and whap
  107. Xunwhap.c     main code for unwhap
  108. Xunyabba.c    main code for unyabba
  109. Xbitout.c     bit output code
  110. Xpercent.c    percent code
  111. Xtexts.c      texts code
  112. Xycoding.4b   Y Coding, paper draft 4b
  113. Xycoding.uu   yabba'd, uuencoded version of ycoding.4b
  114. X
  115. X
  116. X
  117. X2. Requirements
  118. X
  119. XYou should be able to adapt yabbawhap to practically any C platform
  120. X(with 8-bit characters). However, this package was designed on a UNIX
  121. Xsystem. The compressors do not take file names; they only act as
  122. Xfilters. The support files are also oriented towards UNIX.
  123. X
  124. Xyabbawhap has been reported to work on the following systems:
  125. X
  126. X  Sun 4/280, SunOS 4.0.3 (1.00)
  127. X  Sun 4/280, SunOS 4.0.3 (0.98)
  128. X  Sun 4/280, SunOS 4.0.3, gcc (0.98)
  129. X  Sun 4/330, SunOS 4.0.3 (0.95)
  130. X  Sun 4/330, SunOS 4.0.3c (0.98)
  131. X  SPARC?, SunOS 4.1 (0.95)
  132. X  Sun 3/?, SunOS 4.1 (0.95)
  133. X  Sun 3/160, SunOS 4.1 (1.00)
  134. X  Sun 3/480, SunOS 4.1 (0.98)
  135. X  SPARCStation SLC, SunOS 4.1 (0.95)
  136. X  Sun 3/50, SunOS 4.1.1, gcc (0.98)
  137. X  Sun 3/60, SunOS 4.1.1, gcc (0.98)
  138. X  Sun 3/60, SunOS 4.1.1, gcc 1.39 (0.95)
  139. X  SparcStation 2, SunOS 4.1.1 (0.98)
  140. X  DECStation 5400, Ultrix 4.1 (1.00)
  141. X  DECStation 5000/200, Ultrix 4.1 (0.95)
  142. X  DECStation 5000/200, Ultrix 4.1, gcc (0.98)
  143. X  DECStation 5000/200, Ultrix 4.1 (0.98)
  144. X    may need -Olimit 2500 to compile with DEC's ANSI C compiler V2.10
  145. X  DECStation 3100, Ultrix 4.0 (0.95)
  146. X  DECStation 3100, Ultrix 4.0 (0.98)
  147. X  DECSystem 5820, Ultrix 4.1 (0.98)
  148. X  DECSystem 5820, Ultrix 4.1 (1.00)
  149. X  VAX 11/780, BSD 4.3 (0.95)
  150. X  VAX ?, BSD 4.3, gcc 1.39 (0.95)
  151. X  Tek 4316, Utek 4.1, gcc 1.39 (0.95)
  152. X    need -DBRAINDAMAGED
  153. X  Sequent S811, Dynix 3.0.17 (0.95)
  154. X  Sequent Symmetry, Dynix 3.0.17.9 (0.95)
  155. X  Sequent ?, BSD 4.2? (0.95)
  156. X  Apollo DN3500, DOMAIN/OS SR10.2, cc -A cpu,3000 -W0,-opt,2 (1.00)
  157. X  Convex C1-XP, Convex UNIX 9.0, cc -pcc (1.00)
  158. X    need -pcc for the new compiler; -UPTRS faster than -DPTRS
  159. X  IBM RS/6000, AIX 3.1 (0.95)
  160. X  HP 9000s300, HP/UX 7.0 (0.98)
  161. X    -O rather than -O2, optimizer appears buggy anyway
  162. X  NeXT, NeXT Mach 1.0 (0.98)
  163. X  Astronautics ZS, ZSUnix 1.2 (1.00)
  164. X  Amiga, AmigaOS 1.3.2 (0.95)
  165. X  
  166. X(Under gcc, always use -O -fstrength-reduce in place of -O2 in CCOPTS.
  167. XDon't even bother with -finline-functions or the other function-call
  168. Xoptimizations.)
  169. X
  170. XIf your machine isn't in this list, and you get the programs working,
  171. X*please* send a note to me at brnstnd@nyu.edu on the Internet describing
  172. Xwhat you had to do to make the programs compile. (Of course, please also
  173. Xlet me know if you have trouble, or if you have comments, questions, or
  174. Xsuggestions.) I'd rather be flooded with reports and be able to compile
  175. Xa more comprehensive list than have no feedback because everyone assumes
  176. Xsomeone else has talked to me first. You can use FORMLETTER if you want.
  177. XThanks for being a good sport.
  178. X
  179. X
  180. X
  181. X3. How to configure
  182. X
  183. XFirst, run the sysconf shell script. It will try to figure out whether
  184. Xyou have bzero(), memset(), and a certain putchar() bug, and will modify
  185. XMakefile accordingly.
  186. X
  187. XNext, make checkconf. Then run checkconf to see a few facts about your
  188. Xcurrent configuration. You can give it options, like -DNODEMAX=21000,
  189. Xand it will instantly show you how that change will affect the size of
  190. Xthe programs if you add it to CCOPTS in the Makefile. It will also make
  191. Xsure that various constraints are met. checkconf -H shows a help screen.
  192. X
  193. XNext, read through the option descriptions in the Makefile, or print out
  194. Xa copy and peruse it at your leisure. You can configure yabba, unyabba,
  195. Xwhap, and unwhap in several different ways to change compression size,
  196. Xspeed, and power. No single configuration is right for every job.
  197. X
  198. XFinally, armed with checkconf and the option descriptions, decide how
  199. Xyou want to configure the programs. Change Makefile appropriately, and
  200. Xremake checkconf just in case you want to experiment with changes later.
  201. X
  202. XIf you want to get through configuration as quickly as possible, run
  203. X
  204. X  % ./sysconf
  205. X
  206. Xand press return when it asks whether it should make and run checkconf.
  207. XBut don't complain to me about teething trouble if you haven't read
  208. Xthrough all of README and Makefile, as well as the checkconf output.
  209. X
  210. XTwo big caveats: 1. ZEROFILLED should be off on practically any non-UNIX
  211. Xoperating system. 2. If you increase NODEMAX, you probably want to set
  212. X-DNODENUM=65533 unless you know your recipients have compiled with the
  213. Xsame high value of NODEMAX.
  214. X
  215. X
  216. X
  217. X4. How to compile
  218. X
  219. XJust make. You'll get yabba and unyabba. If your optimizer dies, first
  220. Xtry defining -DOPTCANT5 in the Makefile. If that doesn't work, try
  221. X-DOPTCANT2. If that doesn't work, try -DOPTCANT1, or lower the
  222. Xoptimization level.
  223. X
  224. XTo test the programs, run the ``try'' shell script with a filename
  225. Xargument. % ./try yw.shar, for instance. try will give you times and
  226. Xresults for yabba, unyabba, compress, and uncompress on the file. (Note
  227. Xthat it does not test for nonexistent files or symbolic links.)
  228. X
  229. XIf you want to compile whap and unwhap, beware! AP coding is patented.
  230. X(Then again, LZW coding is patented, and people use compress all the
  231. Xtime.) You should understand the information in PATENTS first. Then if
  232. Xyou're curious to see how well AP coding can do, make AP. You can then
  233. Xrun the tryap and tryapy shell scripts the same way as try.
  234. X
  235. XAnother test you can run is to uudecode ycoding.uu and unyabba -m9999
  236. Xthe result, ycoding.Y. You should get a perfect copy of ycoding.4b.
  237. X
  238. X
  239. X5. How to install
  240. X
  241. XBy default, yabba and unyabba are installed in /usr/local/bin; whap and
  242. Xunwhap are installed in /usr/local/bin; yabba.1 and unyabba.1 are
  243. Xinstalled in /usr/man/man1. If you want to change these defaults, edit
  244. XINSTALL. Then run it from a root shell; it will check every action with
  245. Xyou before proceeding.
  246. X
  247. X
  248. X6. TODO list
  249. X
  250. X-E errs
  251. X-f filterfile
  252. X  (Please don't bug me about having yabba take a filename argument
  253. X  until you've seen what -f does.)
  254. X-F
  255. Xflexible -m? report size? (tnx dg)
  256. Xmake no-header and random-bits independent?
  257. Xbetter RESET defaults?
  258. Xput compression in function? will happen with -f
  259. Xrename as fwhap, fyabba, funwhap, fyabba? no
  260. Xuse array trie for top level or two?
  261. END_OF_FILE
  262.   # end of 'README'
  263. fi
  264. if test -f 'Makefile' -a "${1}" != "-c" ; then 
  265.   echo shar: Will not clobber existing file \"'Makefile'\"
  266. else
  267.   echo shar: Extracting \"'Makefile'\" \(9240 characters\)
  268.   sed "s/^X//" >'Makefile' <<'END_OF_FILE'
  269. XCC=cc
  270. XCCOPTS=-O2 -DTYPE=int -DPTRS -DBZERO -DRANDINIT="getpid()"
  271. X
  272. X# These options would be best to compile ``large'' yabba and unyabba
  273. X# on a Sun or other generic 32-bit UNIX machine:
  274. X# CCOPTS=-O2 -DTYPE=int -DPTRS -DBZERO -DZEROFILLED -DRANDINIT="getpid()"
  275. X# On a System V machine, -DMEMZERO should be used instead of -DBZERO.
  276. X# If you want more speed, add -DMOD=131072.
  277. X# For large compressions, try -DNODEMAX=500000 -DMOD=1048576 -DNODENUM=65533.
  278. X# On a small machine, these options might be more appropriate:
  279. X# CCOPTS=-O2 -DTYPE=short -DOPTCANT5
  280. X# To see what the options mean and find out what other options are
  281. X# available, keep reading.
  282. X
  283. X# You should already have run the sysconf script (at least on any UNIX box)
  284. X# to test for system features. sysconf may have modified the CCOPTS line
  285. X# on line 2 of this Makefile.
  286. X
  287. X# To check your configuration decisions before compiling, type
  288. X# % make checkconf
  289. X# % ./checkconf
  290. X# or something equivalent on non-UNIX systems, and read through
  291. X# checkconf's output. You can give checkconf any -D or -U options to
  292. X# see what effect changes will have. On a UNIX machine, you can use
  293. X# the ``try'' shell script to test yabba and unyabba and see how they
  294. X# measure up against compress and uncompress in speed and effectiveness.
  295. X
  296. X# TYPE and PTRS have the biggest effect on how yabba and unyabba operate.
  297. X#
  298. X# TYPE is the type that yabba and unyabba will use for indexing. It
  299. X# should almost certainly be either short or int. If PTRS is defined,
  300. X# yabba (and unyabba and whap, but not unwhap) will use pointers rather
  301. X# than integers wherever possible. On almost all machines yabba runs
  302. X# faster with -DPTRS. More precisely:
  303. X#
  304. X# -UPTRS -DTYPE=short: Use shorts. This is ``small'' yabba and unyabba.
  305. X# -UPTRS -DTYPE=int: Use ints everywhere. On large machines this is
  306. X# usually quite a bit faster than the small version, but also uses
  307. X# twice as much memory.
  308. X# -DPTRS -DTYPE=short: small unwhap, but use pointers in yabba
  309. X# wherever possible. This typically doubles yabba's memory use.
  310. X# -DPTRS -DTYPE=int: Use ints everywhere, with pointers wherever
  311. X# possible. This is ``large'' yabba and unyabba. On large machines it is
  312. X# the fastest configuration, but uses twice as much memory as ``small.''
  313. X#
  314. X# If you want to generate very large-block compressions (see below)
  315. X# on a small machine where int is 16 bits, you may want to try compiling
  316. X# with -DPTRS -DTYPE=long.
  317. X
  318. X# NODEMAX and NODENUM control the compression block size.
  319. X#
  320. X# Any adaptive dictionary compressor has a block size. It can keep
  321. X# track of this much input, or this much output, or this many strings
  322. X# at once, and compress by looking for patterns in the input data.
  323. X# But eventually there's too much to keep track of, and the compressor
  324. X# has to stop adapting to the patterns.
  325. X#
  326. X# In the LZW-based UNIX ``compress'' program, for instance, the block
  327. X# size is stated as the number of bits that the coder can use to
  328. X# identify strings in its dictionary. Once it runs out of identifying
  329. X# numbers, it can't adapt any further.
  330. X#
  331. X# In this compressor, the natural block size is the size of input.
  332. X# NODENUM sets the number of bytes of input that yabba can adapt to at
  333. X# once. Past that it will stick to the current dictionary as long as the
  334. X# patterns seem useful, then clear the strings and start adapting all
  335. X# over again.
  336. X#
  337. X# The user can set NODENUM dynamically with -m. NODEMAX (minimum 512,
  338. X# default 65533---NODEMAX + 2 must fit into TYPE) sets the maximum
  339. X# possible value; several fixed arrays in yabba and unyabba are
  340. X# dimensioned with size NODEMAX. NODENUM defaults to NODEMAX.
  341. X#
  342. X# NODENUM and NODEMAX also control the size of input expected by unyabba.
  343. X# unyabba *must* be given the same -m parameter as yabba was given for
  344. X# compression. That means that if you compress on one machine where
  345. X# yabba has NODENUM set to 60000, you won't be able to decompress on
  346. X# another machine where unyabba has NODEMAX set to 20000. -m has the
  347. X# same effect on portability that -b does for compress (though -m is
  348. X# expressed in somewhat more tractable units).
  349. X
  350. X# MOD (default 65536) is the size of a hash table kept by yabba. It must
  351. X# be a power of two. It should be on a similar order of magnitude as
  352. X# NODEMAX---if it is much too small, the hash table will be too crowded,
  353. X# and if it is much too big, the table will waste memory.
  354. X
  355. X# BITBUFSIZE only affects yabba (at the moment). It is the size of two
  356. X# output buffers kept by the bit-packing coroutines. It defaults to 1000.
  357. X
  358. X# HASHTYPE (default TYPE) is the type used for storing hash values in
  359. X# yabba. It has little effect on whap memory use, so on large machines
  360. X# you may want to set -DHASHTYPE=int even for small whap. However, it
  361. X# does affect memory use in yabba and unyabba, so -DHASHTYPE=short may
  362. X# be useful. In any case, MOD - 1 must fit into unsigned HASHTYPE.
  363. X
  364. X# RESETNUM (default 8192) and RESETFUZZ (default 30, can be negative)
  365. X# control how yabba decides when to clear its dictionary. After NODENUM or
  366. X# the -m limit is reached, yabba checks every RESETNUM input characters
  367. X# whether compression is still worth it. RESETFUZZ has some vaguely
  368. X# defined effect on the meaning of ``worth it'': the higher RESETFUZZ
  369. X# is, the longer yabba holds out before clearing the old patterns. The user
  370. X# can change RESETFUZZ and RESETNUM dynamically, so don't worry about them
  371. X# too much.
  372. X
  373. X# Under -r, yabba needs some reasonably random value from the environment.
  374. X# If you define an integer RANDINIT, yabba will initialize its generator
  375. X# based on that value. Otherwise it has to stick to a default sequence,
  376. X# which does not add as much security. (If you can't think up a good
  377. X# definition for RANDINIT, open up your phone book and pick a number.)
  378. X
  379. X# Many operating systems have brain-damaged putc(): if you put a
  380. X# (perfectly valid) 255 byte, putc() will return EOF, indicating an error.
  381. X# This is the case under Ultrix 3.1 and Convex UNIX 8.0, for instance.
  382. X# You MUST define -DBRAINDAMAGED if sysconf tells you to; otherwise yabba
  383. X# and unyabba will crash mysteriously. Also complain to your vendor.
  384. X
  385. X# If your compiler blows up on yw.c, you may want to set -DOPTCANT5.
  386. X# This will change certain heavily unrolled loops to lightly unrolled.
  387. X# If that still doesn't help, try -DOPTCANT2; then -DOPTCANT1.
  388. X
  389. X# If the internal representation of the NULL pointer on your machine is
  390. X# 0, you can make yabba run slightly faster with -DBZERO or -DMEMZERO.
  391. X# (checkconf will tell you if this is true.) If you have bzero(), use
  392. X# -DBZERO. If you have ANSI memset(), use -DMEMZERO. If you have
  393. X# neither, you're out of luck. MEMZERO is ignored under -DBZERO.
  394. X
  395. X# If you have a machine with particularly fast memory access (perhaps
  396. X# certain microcomputers), you might try defining -DHASHPTRS. This will
  397. X# use some more memory but may run faster. I have not seen any machines
  398. X# where -DHASHPTRS helps.
  399. X
  400. X# Finally, you should set -DZEROFILLED if your operating system
  401. X# guarantees that static arrays are initialized to zeros. Don't set it
  402. X# under -DPTRS if NULL pointers don't have internal representation 0.
  403. X# ZEROFILLED just makes yabba start up a bit faster. (checkconf warns you
  404. X# if it notices a non-zero-filled array, but its test isn't guaranteed.)
  405. X# UNIX systems generally guarantee -DZEROFILLED.
  406. X
  407. X# All of the above comments apply equally to whap as to yabba except
  408. X# where otherwise noted.
  409. X
  410. Xdefault: all
  411. X
  412. XAP: whap unwhap
  413. X
  414. Xall: yabba unyabba
  415. X
  416. Xcheckconf: checkconf.c Makefile
  417. X    $(CC) $(CCOPTS) -o checkconf checkconf.c
  418. X
  419. Xyabba: yabba.o bitout.o percent.o ytexts.o Makefile
  420. X    $(CC) $(CCOPTS) -o yabba yabba.o bitout.o percent.o ytexts.o
  421. X
  422. Xunyabba: unyabba.o percent.o ytexts.o Makefile
  423. X    $(CC) $(CCOPTS) -o unyabba unyabba.o percent.o ytexts.o
  424. X
  425. Xwhap: whap.o bitout.o percent.o wtexts.o Makefile
  426. X    @echo 'Warning! If you use AP coding except for instruction and amusement,'
  427. X    @echo 'you may be infringing on a patent.'
  428. X    @echo 'If you understand this, press return:'
  429. X    @read foo;
  430. X    $(CC) $(CCOPTS) -DWHAP -o whap whap.o bitout.o percent.o wtexts.o
  431. X
  432. Xunwhap: unwhap.o percent.o wtexts.o Makefile
  433. X    $(CC) $(CCOPTS) -DWHAP -o unwhap unwhap.o percent.o wtexts.o
  434. X
  435. Xbitout.o: bitout.c bitout.h Makefile
  436. X    $(CC) $(CCOPTS) -c bitout.c
  437. X
  438. Xpercent.o: percent.c percent.h Makefile
  439. X    $(CC) $(CCOPTS) -c percent.c
  440. X
  441. Xytexts.o: texts.c texts.h Makefile
  442. X    $(CC) $(CCOPTS) -c texts.c
  443. X    mv texts.o ytexts.o
  444. X
  445. Xwtexts.o: texts.c texts.h Makefile
  446. X    $(CC) $(CCOPTS) -DWHAP -c texts.c
  447. X    mv texts.o wtexts.o
  448. X
  449. Xyabba.o: yw.c bitout.h percent.h texts.h huptrie.h Makefile
  450. X    $(CC) $(CCOPTS) -c yw.c
  451. X    mv yw.o yabba.o
  452. X
  453. Xwhap.o: yw.c bitout.h percent.h texts.h huptrie.h Makefile
  454. X    $(CC) $(CCOPTS) -DWHAP -c yw.c
  455. X    mv yw.o whap.o
  456. X
  457. Xunyabba.o: unyabba.c bitout.h percent.h texts.h huptrie.h Makefile
  458. X    $(CC) $(CCOPTS) -c unyabba.c
  459. X
  460. Xunwhap.o: unwhap.c percent.h texts.h Makefile
  461. X    $(CC) $(CCOPTS) -DWHAP -c unwhap.c
  462. X
  463. Xinstall:
  464. X    @echo 'Run INSTALL in a root shell.'
  465. X    exit 1
  466. X
  467. Xclean:
  468. X    @echo 'Why do you want to make clean, anyway?'
  469. X    @echo 'If you changed the Makefile, it knows it should remake.'
  470. X    @echo 'If you want to save space, do make shar and then remove everything.'
  471. X    rm -f unwhap.o unyabba.o whap.o yabba.o yw.o texts.o bitout.o percent.o wtexts.o ytexts.o checkconf whap unwhap yabba unyabba
  472. X
  473. Xshar:
  474. X    shar `cat FILES` > yw.shar
  475. X    chmod 400 yw.shar
  476. END_OF_FILE
  477.   if test 9240 -ne `wc -c <'Makefile'`; then
  478.     echo shar: \"'Makefile'\" unpacked with wrong size!
  479.   fi
  480.   # end of 'Makefile'
  481. fi
  482. if test -f 'ycoding.4b' -a "${1}" != "-c" ; then 
  483.   echo shar: Will not clobber existing file \"'ycoding.4b'\"
  484. else
  485.   echo shar: Extracting \"'ycoding.4b'\" \(31910 characters\)
  486.   sed "s/^X//" >'ycoding.4b' <<'END_OF_FILE'
  487. XY coding
  488. X
  489. XDaniel J. Bernstein
  490. X
  491. XCopyright 1991. All rights reserved.
  492. XDraft 4b, March 19, 1991.
  493. X
  494. XThis is a draft. That means it's supposed to be unreadable, misleading,
  495. Xboring, useless, and generally wrong. Any deviations from the norm are
  496. Xaccidents---happy accidents, but accidents nonetheless. End of warning.
  497. X
  498. X
  499. X----- 1. Introduction
  500. X
  501. X--- LZW coding
  502. X
  503. XFix an alphabet A, and take a string I over that alphabet. Construct a
  504. X``dictionary'' D---a one-to-one mapping from strings to integers---as
  505. Xfollows:
  506. X
  507. X  0. Start by mapping each symbol of A to a unique integer.
  508. X  1. Find the longest prefix p of I contained in D. (Rather, contained
  509. X     in the domain of D. It is convenient to ignore this distinction.)
  510. X  2. Take the next symbol c after p in I.
  511. X  3. Add pc to the dictionary, mapping to another unique integer.
  512. X  4. Strip p from the front of I, so that I begins with c.
  513. X  5. Repeat from step 1 until I is empty (i.e., until step 2 fails).
  514. X
  515. XFor example, say A is the set abcdefghijklmnopqrstuvwxyz, and say I is
  516. Xthe string yabbadabbadabbadoo. D starts with all single characters from
  517. XA. Now the longest match between I and D is I's first character, y; and
  518. Xthe charater after that is a. So we add ya to the dictionary and strip y
  519. Xfrom the front of I.
  520. X
  521. XNow I is abbadabbadabbadoo, and D has all single characters plus ya. The
  522. Xlongest match between D and I is a, so we add ab to the dictionary and
  523. Xremove the a. We continue in this manner until I is empty:
  524. X
  525. X  I                     match  add    new dictionary
  526. X  yabbadabbadabbadoo    y      ya     ya (plus all single characters)
  527. X   abbadabbadabbadoo    a      ab     ya ab
  528. X    bbadabbadabbadoo    b      bb     ya ab bb
  529. X     badabbadabbadoo    b      ba     ya ab bb ba
  530. X      adabbadabbadoo    a      ad     ya ab bb ba ad
  531. X       dabbadabbadoo    d      da     ya ab bb ba ad da
  532. X    abbadabbadoo    ab     abb    ya ab bb ba ad da abb
  533. X      badabbadoo    ba     bad    ya ab bb ba ad da abb bad
  534. X        dabbadoo    da     dab    ya ab bb ba ad da abb bad dab
  535. X          bbadoo    bb     bba    ya ab bb ba ad da abb bad dab bba
  536. X        adoo    ad     ado    ya ab bb ba ad da abb bad dab bba ado
  537. X          oo    o      oo     ya ab bb ba ad da abb bad dab bba ado oo
  538. X           o    o
  539. X
  540. XWhile we construct the dictionary we can output the value of each match
  541. Xunder the dictionary. This produces a sequence of numbers which, as we
  542. Xwill see below, is sufficient to reconstruct the original string. This
  543. Xmapping from strings to sequences of numbers is called LZW coding.
  544. X
  545. XTypically the numbers in the dictionary are chosen sequentially, from 0
  546. Xto |A| - 1 for the initial single-character strings and then from |A| on
  547. Xup. In the above example, the matches are y a b b a d ab ba da bb ad o o,
  548. Xwhich have numbers 24 0 1 1 0 3 27 29 31 28 30 14 14. That sequence is
  549. Xthe result of yabbadabbadabbadoo under LZW coding.
  550. X
  551. X
  552. X--- LZW decoding
  553. X
  554. XHow do we reconstruct the original string if we're given the coded
  555. Xsequence? The secret is to reconstruct the dictionary.
  556. X
  557. X  0. Start by mapping each symbol of A to a unique integer. Set I to the
  558. X     empty string. Read a number from the input, and set p to the
  559. X     corresponding single-character string.
  560. X  1. Append p to I.
  561. X  2. Read a number from the input, and let c be the first character of
  562. X     the corresponding string in the dictionary.
  563. X  3. Add pc to the dictionary, mapping to the next unique integer.
  564. X  4. Set p to the dictionary string corresponding to the number read.
  565. X  5. Repeat from step 1 until end-of-input (i.e., until step 2 fails).
  566. X
  567. XFor example, take the input sequence 24 0 1 1 0 3 27 29 31 28 30 14 14.
  568. XD starts with all single characters from A; p starts as the single
  569. Xcharacter y; and I starts empty.
  570. X
  571. XNow p is appended to I, so that I contains y. The 0 in the input means
  572. Xthat the next character of I is an a; and ya is added to the dictionary.
  573. Xp is then set to a.
  574. X
  575. XNext, p is appended to I, so that I contains ya. The 1 in the input
  576. Xmeans that the next character of I is b; and ab is added to the
  577. Xdictionary. p is then set to b. We continue this way through the entire
  578. Xinput:
  579. X
  580. X  input  c   added    new p   I
  581. X  24                  y       y
  582. X  0      a   (ya,26)  a       ya
  583. X  1      b   (ab,27)  b       yab
  584. X  1      b   (bb,28)  b       yabb
  585. X  0      a   (ba,29)  a       yabba
  586. X  3      d   (ad,30)  d       yabbad
  587. X  27    *a*  (da,31)  ab      yabbadab      27 is ab, so *a* is the 1st char
  588. X  29    _b_  (abb,32) ba      yabbadabba    29 is ba, so _b_ is the 1st char
  589. X  31     d   (bad,33) da      yabbadabbada
  590. X  28     b   (dab,34) bb      yabbadabbadabb
  591. X  30     a   (bba,35) ad      yabbadabbadabbad
  592. X  14     o   (ado,36) o       yabbadabbadabbado
  593. X  14     o   (oo,37)  o       yabbadabbadabbadoo
  594. X
  595. XNotice the slightly twisted statement of steps 2 through 4. p is set to
  596. Xthe dictionary string corresponding to the number read from the input,
  597. Xbut first c is set to the first character of that string, and the old pc
  598. Xis added to the dictionary. This roundabout presentation is necessary
  599. Xbecause the number on the input may be the number of the very last
  600. Xdictionary string added---and that last string depends on the first
  601. Xcharacter of the current string. This overlap is always safe but is one
  602. Xof the first problems to look out for in a new implementation.
  603. X
  604. X
  605. X--- So who cares about this LZW stuff anyway?
  606. X
  607. XWhat's the point of LZW coding? When the input string has lots of the
  608. Xsame characters or sequences of characters, the dictionary will rapidly
  609. Xgrow to include those sequences. Then a single number in the output
  610. Xsequence might represent several characters of input, and will use less
  611. Xspace.
  612. X
  613. XFor example, take the simplest natural encoding of a string over our
  614. Xlowercase alphabet A. There are 26 symbols, so we can represent each
  615. Xwith 5 bits. Our string yabbadabbadabbadoo has 18 characters and takes
  616. X90 bits under this encoding.
  617. X
  618. XOn the other hand, the string after encoding has just 13 numbers:
  619. X24 0 1 1 0 3 27 29 31 28 30 14 14. For these values there are 26 27 28
  620. X29 30 31 32 33 34 35 36 37 38 choices respectively, so they take 5 5 5 5
  621. X5 5 5 6 6 6 6 6 6 bits in the natural way, for a total of just 71 bits.
  622. X
  623. XMost strings that come up in practice have similar redundancy, and LZW
  624. Xcoding will produce an output that takes less space than its input. This
  625. Xis why LZW coding is usually called LZW compression. It often reduces
  626. Xlonger strings to 50% or even 30% of their original size, so that they
  627. Xtake a fraction as much disk space and communication time as they would
  628. Xin their uncompressed form.
  629. X
  630. X
  631. X--- A bit of jargon
  632. X
  633. XMany audio and video compression methods throw away some information.
  634. XThey don't reconstruct exactly the original pictures and sounds, but
  635. Xnobody really notices. These are called inexact, or sometimes lossy,
  636. Xcompressors. In contrast, LZW always lets you get back exactly the
  637. Xoriginal string. It is an exact, or lossless, compressor.
  638. X
  639. XAny compressor that splits its input into substrings and codes the
  640. Xstrings with a dictionary is called (logically enough) a dictionary
  641. Xcompressor.
  642. X
  643. XA substring of an input string---particularly a substring that is coded
  644. Xas a single output number---is called a ``phrase.'' In LZW, one string
  645. Xis added to the dictionary per phrase.
  646. X
  647. XSome compression methods use fixed tables: ``the'' becomes a special,
  648. Xsingle character, ``of'' becomes another, etc. They're called static, or
  649. Xnonadaptive, compressors. Others, like LZW, build their dictionaries
  650. Xdynamically to adapt to any input; LZW is an example of an adaptive
  651. Xcompressor. Somewhere in between are compressors that make two passes
  652. Xover the input, building a dictionary the first time through and then
  653. Xproducing output the second time through. They're called semiadaptive.
  654. X
  655. XOne useless theoretical property of LZW is that it is universal. This
  656. Xmeans that on a certain wide class of inputs it will give as close as
  657. Xyou want to the best possible compression of any method. The longer your
  658. Xstrings are, the closer it comes to optimal. Universality doesn't make
  659. Xone whit of difference in practice---to get within 1% of optimal with
  660. XLZW you'd have to start compressing the planet---but it generally
  661. Xindicates that a method is both simple and trustworthy. Non-universal
  662. Xcompressors are usually much more complicated, and will fail miserably
  663. Xon inputs they weren't designed specifically to handle.
  664. X
  665. X
  666. X
  667. X----- 2. Implementing LZW
  668. X
  669. X--- Encoding
  670. X
  671. XThe most natural way to find the longest match between I and strings in
  672. XD is one character at a time. Start with p as the first character of I
  673. X(or as the null string if that is more convenient). Read the next
  674. Xcharacter, c. If pc is in the dictionary, set p to pc and repeat.
  675. XOtherwise p and c are set.
  676. X
  677. XSo the dictionary has to support two basic operations: searching for pc
  678. Xif p is known to be there already, and adding pc if it is not there.
  679. XMost implementors use some form of trie---array trie, list trie, hash
  680. Xtrie, huptrie---for this job. The array trie, as in Woods' ``hyper-LZ''
  681. X[9], offers extreme speed at the expense of |A| (typically 256) words
  682. Xof memory for each string in the trie. The huptrie and straight hash
  683. Xtrie use only a small amount of memory per string but still allow
  684. Xreasonably fast searches in the average case. We will not consider these
  685. Xstructures in further detail.
  686. X
  687. XIn any case at most a fixed number of operations happen for every input
  688. Xcharacter, so LZW coding takes linear time no matter how long the input
  689. Xis. Unfortunately, computers don't have infinite memory. Implementations
  690. Xtypically limit the dictionary to some size, usually between 1024 and
  691. X65536 strings. When the dictionary reaches that size it can either
  692. Xremain fixed for the rest of the input, or it can be cleared and start
  693. Xfrom single characters again. The second strategy effectively breaks the
  694. Xinput into ``blocks'' with independent dictionaries. If the input
  695. X``feels'' different in different blocks, blocking will produce good
  696. Xresults, because it will weed useless strings out of the dictionary.
  697. X
  698. XThe ``compress'' program [8] introduced an important blocking variant.
  699. XInstead of clearing the dictionary as soon as it reaches its maximum
  700. Xsize, compress periodically checks how well it is doing. It will only
  701. Xclear the dictionary when its compression ratio deteriorates. This way
  702. Xthe blocks adapt to the input. Note that all of these blocking
  703. Xtechniques require space for a special output code to clear the
  704. Xdictionary.
  705. X
  706. XAnother variant is LRU replacement: the least-recently-used strings are
  707. Xremoved from the dictionary at some opportune time. This provides a
  708. Xsmoother transition between blocks than clearing the dictionary.
  709. XUnfortunately, it is difficult to find good heuristics for when to
  710. Xremove what strings. Blocking is still more of an art than a science.
  711. X
  712. X
  713. X--- Preparing for encryption
  714. X
  715. XIt is very useful to compress a message before encrypting it, as
  716. Xcompression removes much of the statistical regularity of straight text.
  717. XHowever, the usual coding leaves a lot of redundancy. If the dictionary
  718. Xhas 33 strings, for example, and 6 bits are used to represent a choice
  719. Xamong those strings, then the high bit will almost always be 0. These
  720. Xhigh bits come in predictable locations, so an attacker can almost
  721. Xalways figure out the key given a long enough stretch of compressed
  722. Xtext.
  723. X
  724. XTo prevent this, the compressor should introduce random bits as follows:
  725. XGiven a choice between 0 and 40, 0 through 22 are encoded as either
  726. Xthemselves or from 41 through 63. The choice should be made with a
  727. Xhigh-delay random number generator such as a subtractive generator.
  728. X23 through 40 are always encoded as themselves. This method greatly
  729. Xreduces the amount of extra information available per bit without
  730. Xappreciably slowing down the coding. Because random bits are used at
  731. Xunpredictable times, an attacker cannot easily take advantage of the
  732. Xdeterminism of the pseudo-random generator.
  733. X
  734. XMost implementations also add a recognizable header to compressed text.
  735. XThis header should be removed before encryption.
  736. X
  737. X
  738. X--- Decoding
  739. X
  740. XLZW decoding is even easier than encoding: the dictionary does not have
  741. Xto support searching. The easiest (and generally fastest) method is to
  742. Xkeep I in memory as it is reconstructed, and to keep track of which
  743. Xsubstring of I a given dictionary number corresponds to. To add pc to
  744. Xthe dictionary means to add the pair (pointer to start of pc within I,
  745. Xlength of pc) at the right spot in an array indexed by dictionary
  746. Xnumbers. There are methods which take slightly less memory than this,
  747. Xbut they are slower.
  748. X
  749. X
  750. X
  751. X----- 3. MW and AP coding
  752. X
  753. X--- MW: Adapting better
  754. X
  755. XLZW adapts to its input relatively slowly: strings in the dictionary
  756. Xonly get one character longer at a time. If LZW is fed a million
  757. Xconsecutive x's, its longest dictionary string will only have around
  758. X1400 x's, and it will only achieve around 1000:1 compression. Is there
  759. Xany better way for it to notice the redundancy?
  760. X
  761. XThe answer is yes. Instead of adding p plus one character of the next
  762. Xphrase to the dictionary, we can add p plus the entire next phrase to
  763. Xthe dictionary. This defines MW coding. For example:
  764. X
  765. X  I                     match  added to dictionary
  766. X  yabbadabbadabbadoo    y        
  767. X   abbadabbadabbadoo    a      ya (concatenation of last two matches)
  768. X    bbadabbadabbadoo    b      ab
  769. X     badabbadabbadoo    b      bb
  770. X      adabbadabbadoo    a      ba
  771. X       dabbadabbadoo    d      ad
  772. X    abbadabbadoo    ab     dab
  773. X      badabbadoo    ba     abba
  774. X        dabbadoo    dab    badab
  775. X           badoo    ba     dabba
  776. X         doo    d      bad
  777. X          oo    o      do
  778. X           o    o
  779. X
  780. XEven such a short example shows how quickly MW begins to adapt. By the
  781. Xfifteenth character ``dabba'' is already established as a dictionary
  782. Xphrase. On the other hand, MW will miss shorter phrases where there is
  783. Xless redundancy, so it generally performs only somewhat better than LZW
  784. Xin practice. In this example it outputs 13 numbers, just like LZW. But
  785. Xgiven a million x's it will end up with a dictionary string of length
  786. Xaround half a million, and it will output just 30 bytes.
  787. X
  788. X
  789. X
  790. X
  791. X--- Problems of MW
  792. X
  793. XMW lacks some properties of LZW that we don't realize are so helpful
  794. Xuntil they are taken away. Most importantly, not every prefix of a
  795. Xdictionary string is in the dictionary. This means that the
  796. Xcharacter-at-a-time search method we saw for LZW doesn't work. Instead,
  797. Xevery prefix of a string in the dictionary must be added to the trie,
  798. Xand every node in the trie must be given a tag saying whether it is in
  799. Xthe dictionary or not. Furthermore, finding the longest string may
  800. Xrequire backtracking: if the dictionary contains xxxx and xxxxxxxx, we
  801. Xdon't know until we've read to the eighth character of xxxxxxxy that we
  802. Xhave to choose the shorter string. This seems to imply that MW coding
  803. Xrequires backtracking and hence is fundamentally slower than LZW coding.
  804. X(Decoding can be made reasonably fast, though.)
  805. X
  806. XAnother problem is that a string may be added to the dictionary twice.
  807. XThis rules out certain implementations and requires extra care in
  808. Xothers. It also makes MW a little less safe than LZW before encryption.
  809. X
  810. X
  811. X--- AP: Adapting faster
  812. X
  813. XThere is a natural way to preserve the good adaptation of MW while
  814. Xeliminating its need for backtracking: instead of just concatenating the
  815. Xlast two phrases and putting the result into the dictionary, put all
  816. Xprefixes of the concatenation into the dictionary. (More precisely, if S
  817. Xand T are the last two matches, add St to the dictionary for every
  818. Xnonempty prefix t of T, including T itself.) This defines AP coding. For
  819. Xexample:
  820. X
  821. X  I                     match  added to dictionary
  822. X  yabbadabbadabbadoo    y        
  823. X   abbadabbadabbadoo    a      ya
  824. X    bbadabbadabbadoo    b      ab
  825. X     badabbadabbadoo    b      bb
  826. X      adabbadabbadoo    a      ba
  827. X       dabbadabbadoo    d      ad
  828. X    abbadabbadoo    ab     da, dab        (d + all prefixes of ab)
  829. X      badabbadoo    ba     abb, abba      (ab + all prefixes of ba)
  830. X        dabbadoo    dab    bad, bada, badab
  831. X           badoo    ba     dabb, dabba
  832. X         doo    d      bad
  833. X          oo    o      do
  834. X           o    o
  835. X
  836. XSince AP adds more strings to the dictionary, it takes more bits to
  837. Xrepresent a choice. However, it does provide a fuller range of matches
  838. Xfor the input string, and in practice it achieves slightly better
  839. Xcompression than MW in quite a bit less time.
  840. X
  841. X
  842. X----- 4. Y coding
  843. X
  844. X--- Completing the square
  845. X
  846. XLZW adds one dictionary string per phrase and increments strings by one
  847. Xcharacter at a time. MW adds one dictionary string per phrase and
  848. Xincrements strings by several characters at a time. AP adds one
  849. Xdictionary string per input character and increments strings by several
  850. Xcharacters at a time. These properties define three broad classes of
  851. Xmethods and point naturally to a fourth: coders that add one dictionary
  852. Xstring per input character and increment strings by one character at a
  853. Xtime. An example of such a method is Y coding. (It is worth noting at
  854. Xthis point that LZ77 variants are characterized by adding several
  855. Xdictionary strings per input character.)
  856. X
  857. X
  858. X--- The incomprehensible definition
  859. X
  860. XY coding is defined as follows: The dictionary starts with all single
  861. Xcharacters. One string pc starting at each input position is added to
  862. Xthe dictionary, where p is in the dictionary before that character and
  863. Xpc is not.
  864. X
  865. XTo put it differently, ``yowie'' appears in the dictionary as soon as
  866. Xthe regular expression yo.*yow.*yowi.*yowie matches the text. It is
  867. Xadded at the final e. So yabbadabbadabbadoo leads to the dictionary ya,
  868. Xab, bb, ba, ad, da, abb, bba, ada, dab, abba, bbad, bado, ado, oo.
  869. X
  870. XWe haven't defined the coding yet. While we build the dictionary, we
  871. Xkeep track of a current longest match (initially empty). Right after
  872. Xreading an input character and before integrating it into the
  873. Xdictionary, we see whether the longest match plus that character is
  874. Xstill in the dictionary *constructed before the start of that longest
  875. Xmatch*. If so, we use that as the new longest match, and proceed.
  876. XOtherwise, we output the number of the longest match, and set the
  877. Xlongest match to just that new character.
  878. X
  879. XTo decode, we read these matches, one by one. We take each one as a
  880. Xsequence of characters as defined by the dictionary, and output that
  881. Xsequence. Meanwhile we take each character and feed it as input to the
  882. Xdictionary-building routine.
  883. X
  884. X
  885. X--- A comprehensible example
  886. X
  887. XWe can run through the string keeping track of dictionary matches, as
  888. Xfollows:
  889. X
  890. X  I                        add    current matches
  891. X  abcabcabcabcabcabcabcx          a
  892. X   bcabcabcabcabcabcabcx   ab     b
  893. X    cabcabcabcabcabcabcx   bc     c
  894. X     abcabcabcabcabcabcx   ca     a
  895. X      bcabcabcabcabcabcx          ab b
  896. X       cabcabcabcabcabcx   abc       bc c
  897. X        abcabcabcabcabcx   bca          ca a
  898. X         bcabcabcabcabcx   cab             ab  b
  899. X          cabcabcabcabcx            _____  abc bc  c
  900. X           abcabcabcabcx   abca    / \   \___  bca ca a
  901. X            bcabcabcabcx   bcab   cab ab   b \____  \_/
  902. X             cabcabcabcx   cabc       abc  bc   c \__/
  903. X              abcabcabcx              abca bca  ca   a
  904. X               bcabcabcx   abcab           bcab cab  ab    b
  905. X                cabcabcx   bcabc                cabc abc   bc   c
  906. X                 abcabcx   cabca                     abca  bca  ca  a
  907. X                  bcabcx           ,-----------------abcab bcab cab ab b
  908. X                   cabcx   abcabc  `--bcabc cabc  abc    bc    c
  909. X            abcx   bcabca           cabca abca   bca   ca   a
  910. X             bcx   cabcab                 abcab  bcab  cab  ab  b
  911. X              cx                          abcabc bcabc cabc abc bc c
  912. X               x   abcabcx x
  913. X                bcabcx
  914. X                 cabcx
  915. X                  abcx
  916. X                   bcx
  917. X                cx
  918. X
  919. XThe strings on the right side are the current matches-so-far after each
  920. Xinput character. We start with no matches. When we read a character, we
  921. Xappend it to each match so far; if the results are in the dictionary, we
  922. Xmake them the new matches, and add the character as a match by itself.
  923. XIf any of them are not in the dictionary we take them out of the list
  924. Xand add them to the dictionary.
  925. X
  926. XBefore reading the fifth c, for example, the matches are bcab, cab, ab,
  927. Xand b. We append c to each one: bcabc doesn't match, so we add it to the
  928. Xdictionary. The rest are still in the dictionary, so our new list is
  929. Xcabc, abc, bc, and a lone c. And so on.
  930. X
  931. XWhen the x is read, the current list is abcab bcab cab ab b. Now none of
  932. Xabcabx bcabx cabx abx bx are in the dictionary, so we add all of them,
  933. Xand the list becomes just a single x.
  934. X
  935. X
  936. X--- The crucial observation
  937. X
  938. XIt is not clear so far that Y is a linear-time algorithm: each input
  939. Xcharacter demands additions to several matches. However, *every
  940. Xsubstring of a dictionary string is in the dictionary*. This is clear
  941. Xfrom the regular-expression characterization of dictionary strings: if
  942. Xyo.*yow.*yowi.*yowie matches the text, then ow.*owi.*owie (for example)
  943. Xcertainly does as well.
  944. X
  945. XSay the current match list is wonka onka nka ka a, and we read the
  946. Xcharacter x. The next list has to be one of the following:
  947. X
  948. X  wonkax onkax nkax kax ax x
  949. X         onkax nkax kax ax x
  950. X               nkax kax ax x
  951. X                    kax ax x
  952. X                        ax x
  953. X                           x
  954. X
  955. XIf onkax matches, for example, then nkax must match as well, and so must
  956. Xkax and ax and x.
  957. X
  958. XSo the match list will always consist of one string and its suffixes.
  959. XHence we can keep track of just the longest string in the match list.
  960. XFor example, with the input string oompaoompapaoompaoompapa:
  961. X
  962. X  input  test   add    match
  963. X  o                    o
  964. X  o      oo     oo     o
  965. X  m      om     om     m
  966. X  p      mp     mp     p
  967. X  a      pa     pa     a
  968. X  o      ao     ao     o
  969. X  o      oo            oo
  970. X  m      oom    oom    om
  971. X  p      omp    omp    mp
  972. X  a      mpa    mpa    pa
  973. X  p      pap    pap
  974. X                ap     p
  975. X  a      pa            pa
  976. X  o      pao    pao    ao
  977. X  o      aoo    aoo    oo
  978. X  m      oom           oom
  979. X  p      oomp   oomp   omp
  980. X  a      ompa   ompa   mpa
  981. X  o      mpao   mpao
  982. X            pao    ao
  983. X  o      aoo           aoo
  984. X  m      aoom   aoom   oom
  985. X  p      oomp          oomp
  986. X  a      oompa  oompa  ompa
  987. X  p      ompap  ompap
  988. X            mpap   pap
  989. X  a      papa   papa
  990. X                apa    pa
  991. X
  992. X
  993. X--- A comprehensible definition
  994. X
  995. XHere is another definition of how to construct the Y dictionary, based
  996. Xon the chart above.
  997. X
  998. X  0. Start with the dictionary mapping every character of A to a unique
  999. X     integer. Set m to the empty string.
  1000. X  1. Append the next character c of I to m.
  1001. X  2. If m is not in the dictionary, then add m to the dictionary, remove
  1002. X     the first character of m, and repeat this step.
  1003. X  3. Repeat from step 1 until the input is exhausted.
  1004. X
  1005. XWe must be careful in defining output: the output is not synchronized
  1006. Xwith the dictionary additions, and we must be careful not to have the
  1007. Xlongest output match overlap itself. To this end we split the dictionary
  1008. Xinto two parts, the first part safe to use for the output, the second
  1009. Xpart not safe.
  1010. X
  1011. X  0. Start with S mapping each single character to a unique integer;
  1012. X     T empty; m empty; and o empty. (S and T are the two parts of the
  1013. X     dictionary.)
  1014. X  1. Read a character c. If oc is in S, set o to oc; otherwise output
  1015. X     S(o), set o to c, add T to S, and remove everything from T.
  1016. X  2. While mc is not in S or T, add mc to T (mapping to the next
  1017. X     available integer), and chop off the first character of m.
  1018. X  3. After m is short enough that mc is in the dictionary, set m to mc.
  1019. X  4. Repeat as long as there are enough input characters (i.e., until
  1020. X     step 1 fails).
  1021. X  5. Output S(o) and quit.
  1022. X
  1023. XHere's how to decode:
  1024. X
  1025. X  0. Initialize (D,m) as above.
  1026. X  1. Read D(o) from the input and take the inverse under D to find o.
  1027. X  2. As long as o is not the empty string, find the first character c of
  1028. X     o, and update (D,m) as above. Also output c and chop it off from
  1029. X     the front of o.
  1030. X  3. Repeat from step 1 until the input is exhausted.
  1031. X
  1032. XThe coding only requires two fast operations on strings in the
  1033. Xdictionary: testing whether sc is there if s's position is known, and
  1034. Xfinding s's position given cs's position. The decoding only requires the
  1035. Xsame operations plus finding the first character of a string given its
  1036. Xspot in the dictionary.
  1037. X
  1038. X
  1039. X--- Some properties of Y coding
  1040. X
  1041. XWe propose ``per-phrase dictionary'' to describe the dictionaries
  1042. Xconstructed by LZW and MW, ``per-character dictionary'' for AP and Y.
  1043. XWe also propose ``phrase-increment'' to describe MW and AP,
  1044. X``character-increment'' for LZW and Y. More precisely, a per-phrase
  1045. Xdictionary is one which contains one string per output phrase, while a
  1046. Xper-character dictionary contains one string per input character. Each
  1047. Xstring in a character-increment dictionary is exactly one character
  1048. Xlonger than a string added at a previous step; in contrast, a string in
  1049. Xa phrase-increment dictionary can be much longer than any of its
  1050. Xprefixes formerly in the dictionary. According to this terminology,
  1051. XY is an exact character-increment per-character dictionary compressor.
  1052. X
  1053. XY has a similar feel to LZJ, which has a dictionary consisting of all
  1054. Xunique substrings up to a certain length in a block of the input.
  1055. XHowever, Y can adapt much more effectively to redundant text.
  1056. X
  1057. X
  1058. X
  1059. X----- 5. Results
  1060. X
  1061. XThe author has implemented Y coding [2] along with, for instruction and
  1062. Xamusement, AP coding. In this section we survey various implementation
  1063. Xissues and compare the effectiveness of the coding methods explained
  1064. Xhere.
  1065. X
  1066. XThe author's implementation, yabbawhap, uses a huptrie [3] for the
  1067. Xdictionary. yabba keeps track of the separate dictionaries S and T for Y
  1068. Xcoding by remembering the highest position within D that is ``safe''
  1069. Xinside S; all higher positions are in T.
  1070. X
  1071. Xyabbawhap uses compress's strategy of adaptive blocking. The user may
  1072. Xvary most aspects of compression dynamically, including two parameters
  1073. Xof the heuristic used to control blocking.
  1074. X
  1075. XHere are results of these methods on the Bell-Witten-Cleary text corpus,
  1076. Xalong with a highly redundant 180489-byte ``makelog'' added by the
  1077. Xauthor to show an extreme case.
  1078. X
  1079. X     __bib__book1__book2____geo_makelog___news___obj1___obj2_paper1_paper2_
  1080. XZ12  54094 394419 325147  78026   34757 230765  16528 160099  29433  40881
  1081. XZ14  46817 357387 281354  77696   25647 202594  14048 138521  25077  37196
  1082. XZ16__46528_332056_250759__77777___25647_182121__14048_128659__25077__36161_
  1083. XMW___41040_336793_230862__80296____8299_168652__13273_109266__22749__34234_
  1084. XAP2  47056 389702 297205  84582   20925 219665  13824 134547  26937  39415
  1085. XAP6  40770 338046 261270  79471   14762 190502  13824 123323  22413  34637
  1086. XAP3__40311_322178_228978__80106____8821_167896__13825_113296__22414__33320_
  1087. XY2   46882 363339 287110  80817   28159 212617  13858 141783  26131  38037
  1088. XY6   40874 320622 256578  76275   21220 185097  13858 125900  22452  33671
  1089. XY3___40456_306813_229851__76695___14411_168287__13859_114323__22453__32733_
  1090. X
  1091. X    paper3_paper4_paper5_paper6_____pic__progc__progl__progp__trans_
  1092. XZ12  23567   7091   6670  22333   66236  21825  31987  22936  46185
  1093. XZ14  22163   6957   6580  18695   63277  19143  27116  19209  39605
  1094. XZ16__22163___6957___6580__18695___62215__19143__27148__19209__38240_
  1095. XMW___21495___6697___6169__16899___65102__16976__22223__15095__27742_
  1096. XAP2  22293   6595   6146  19770   74061  18868  27191  17962  38781
  1097. XAP6  20869   6595   6146  16786   68349  16691  22716  15138  30415
  1098. XAP3__20870___6596___6147__16787___67980__16692__22451__15139__28056_
  1099. XY2   21609   6443   6033  19418   71952  18897  27607  19429  40444
  1100. XY6   20355   6443   6033  16677   66117  17063  23625  16616  33026
  1101. XY3___20356___6444___6034__16678___65377__17064__23512__16617__31300_
  1102. X
  1103. XZ12 is LZW with 12 bits (i.e., a dictionary of at most 4096 strings),
  1104. Xusing compress -b12. MW is MW using the author's squeeze program [4],
  1105. Xwith a dictionary of at most 300000 strings (roughly equivalent to
  1106. X1500000 input characters). AP2 is AP with an input block size of 21000,
  1107. Xusing whap -m21000; AP6 has a block size of 65533, and AP3 has a block
  1108. Xsize of 300000. Y is like AP but using yabba.
  1109. X
  1110. XY is notably effective upon book1 and news.
  1111. X
  1112. XXXX what else do people want to see in this section?
  1113. X
  1114. X
  1115. X
  1116. X----- 6. Conclusion
  1117. X
  1118. X--- Life goes on
  1119. X
  1120. XY coding is not much more complex than LZW coding and produces generally
  1121. Xbetter results. It is one of the most effective non-Huffman-based
  1122. XLZ78-style compressors.
  1123. X
  1124. X
  1125. X--- How to achieve fame and fortune
  1126. X
  1127. XIt may be possible to implement Y so that the decoding does not have to
  1128. Xdo all the work of the coding. In particular, three-fourths of the
  1129. Xdictionary strings are typically not used at all; they should not have
  1130. Xto be handled during decoding. Even if Y cannot be sped up, there is
  1131. Xprobably some character-increment per-character dictionary compressor
  1132. Xthat achieves similar results to Y but runs as quickly as LZW or AP.
  1133. XThis is a area for future research.
  1134. X
  1135. XWe have not discussed different ways to code the output numbers. Huffman
  1136. Xcoding and arithmetic coding both produce quite respectable improvements
  1137. Xover and above the compression of the basic Y method. Little is known
  1138. Xabout the best way to code a sequence from a dynamically expanding
  1139. Xalphabet; it is a bit counterintuitive that semiadaptive Huffman coding
  1140. Xupon an output Y sequence can produce worse results than adaptive
  1141. XHuffman coding.
  1142. X
  1143. XIt would be interesting to compare a straight modeller with Y plus a
  1144. XHuffman coder to see which produces better results.
  1145. X
  1146. X
  1147. X--- Acknowledgments
  1148. X
  1149. XThe author would like to thank James Woods for his support and
  1150. Xencouragement, as well as for many copies of papers; Richard Stallman,
  1151. Xfor motivating the author to find Y coding; and Herbert J. Bernstein for
  1152. Xgeneral comments and for suggesting the order of presentation of this
  1153. Xmaterial.
  1154. X
  1155. X
  1156. X--- So who are these LZWMWAPY people anyway?
  1157. X
  1158. XLZW stands for Lempel, Ziv, Welch. In 1977 Ziv and Lempel discovered the
  1159. Xfirst in what are now called the LZ family of dictionary compressors.
  1160. XThe original LZ algorithms were like LZW, but transmitted both p and c
  1161. Xand then skipped past pc. They also started with a dictionary of just
  1162. Xthe null string. (For detailed surveys of various LZ methods, the reader
  1163. Xshould consult [1], [5], [7], [11].) Welch popularized the LZ variant,
  1164. Xnow called LZW, in which the extra character was not transmitted but
  1165. Xbecame the first character of the next phrase.
  1166. X
  1167. XMiller and Wegman independently discovered several LZ variants in 1984,
  1168. Xincluding LZW and MW. In fact, Seery and Ziv had in 1978 [6] proposed an
  1169. XLZ variant where two adjacent phrases were concatenated; this is related
  1170. Xto MW in approximately the same way that LZ is related to LZW. (Seery
  1171. Xand Ziv also introduced an important improvement for binary alphabets:
  1172. Xif 01101 and 01100 are in the dictionary, there is no way that 0110 can
  1173. Xpossibly be a longest match, so it can effectively be removed from the
  1174. Xdictionary.)
  1175. X
  1176. XAP stands for ``all prefixes.'' It was originally discovered by Storer
  1177. Xin 1988 (?) and independently rediscovered by this author in 1990.
  1178. X
  1179. XY actually does stand for yabbadabbadoo. The author discovered Y coding
  1180. Xon December 26, 1990; he used yabbadabbadabbadoo as an example in
  1181. Xexplaining the method to Woods the next day. Woods replied [10] ``I'll
  1182. Xhave to look at your yabbadabbadoo code again to see how it differs from
  1183. XLZR.'' The author promptly adopted ``Y coding'' as the official name.
  1184. X(Ross Williams has suggested [12] that ``LZDB coding'' might be more
  1185. Xappropriate.)
  1186. X
  1187. X
  1188. X--- References
  1189. X
  1190. XYeah, yeah, I'm still writing up proper citations. XXX
  1191. X
  1192. X[1]  Bell, Witten, Cleary, compression article, 1989
  1193. X[2]  Bernstein, yabbawhap program, 1990-1991
  1194. X[3]  Bernstein, huptrie article, 1990
  1195. X[4]  Bernstein, squeeze program, 1989
  1196. X[5]  Miller and Wegman, compression article, 1987
  1197. X[6]  Seery and Ziv, LZ78 extensions article, 1978
  1198. X[7]  Storer, compression book, 1988
  1199. X[8]  Woods et al., compress program, 1985
  1200. X[9]  Woods, private communication, 1990
  1201. X[10] Woods, private communication, 1990
  1202. X[11] Williams, compression book, 1991
  1203. X[12] Williams, private communication, 1991
  1204. END_OF_FILE
  1205.   if test 31910 -ne `wc -c <'ycoding.4b'`; then
  1206.     echo shar: \"'ycoding.4b'\" unpacked with wrong size!
  1207.   fi
  1208.   # end of 'ycoding.4b'
  1209. fi
  1210. echo shar: End of archive 1 \(of 4\).
  1211. cp /dev/null ark1isdone
  1212. MISSING=""
  1213. for I in 1 2 3 4 ; do
  1214.     if test ! -f ark${I}isdone ; then
  1215.     MISSING="${MISSING} ${I}"
  1216.     fi
  1217. done
  1218. if test "${MISSING}" = "" ; then
  1219.     echo You have unpacked all 4 archives.
  1220.     rm -f ark[1-9]isdone
  1221. else
  1222.     echo You still must unpack the following archives:
  1223.     echo "        " ${MISSING}
  1224. fi
  1225. exit 0
  1226. exit 0 # Just in case...
  1227.